// Fill out your copyright notice in the Description page of Project Settings.


#include "Projectile.h"
#include "Components/BoxComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Kismet/gameplayStatics.h"
#include "Particles/ParticleSystem.h"
#include "Particles/ParticleSystemComponent.h"
#include "Sound/SoundBase.h"
#include "Blaster/Character/BlasterCharacter.h"
#include "Blaster/Blaster.h"
#include "NiagaraComponent.h"
#include "NiagaraFunctionLibrary.h"

AProjectile::AProjectile()
{
	bReplicates = true;
	PrimaryActorTick.bCanEverTick = true;
	CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionBox"));
	SetRootComponent(CollisionBox);
	//SetCollisionObjectType：改变对象移动时的碰撞轨道
	CollisionBox->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
	CollisionBox->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
	CollisionBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
	CollisionBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
	CollisionBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block);
	CollisionBox->SetCollisionResponseToChannel(ECC_SkeletalMesh, ECollisionResponse::ECR_Block);
}


void AProjectile::BeginPlay()
{
	Super::BeginPlay();
	if(Tracer)
	{
		//SpawnEmitterAttached：播放具体特效吸附并跟随具体组件
		//SpawnEmitterAtLocation：播放具体特效在指定的位置或旋转
		TracerComponent = UGameplayStatics::SpawnEmitterAttached(Tracer, CollisionBox, NAME_None, GetActorLocation(), GetActorRotation(), EAttachLocation::KeepWorldPosition);
	}
	if(HasAuthority())
	{
		CollisionBox->OnComponentHit.AddDynamic(this, &AProjectile::OnHit);
	}
}

void AProjectile::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp,
	FVector NormalImpulse, const FHitResult& Hit)
{
	Destroy();
}

void AProjectile::DestroyTimeFinished()
{
	Destroy();
}

void AProjectile::ExplodeDamage()
{
	// GetInstigator：获取发起者
	APawn* FiringPawn = GetInstigator();
	if (FiringPawn && HasAuthority())
	{
		//GetController：返回此Actor的控制器
		AController* FiringController = FiringPawn->GetController();
		if (FiringController)
		{
			//伤害在本半径内本地权威Actor，只会对ECC_Visibility轨道的ECR_Block造成影响
			UGameplayStatics::ApplyRadialDamageWithFalloff(
				this, //世界对象
				Damage, //基本伤害
				10.f, //最小伤害半径
				GetActorLocation(), //原点
				DamageInnerRadius, //满伤害区域
				DamageOuterRadius, //最小伤害区域
				1.f, //从满伤害区域到最小伤害区域的衰减指数
				UDamageType::StaticClass(), //伤害类型
				TArray<AActor*>(), //忽略Actors
				this, //伤害造成者
				FiringController
			);
		}
	}
}

void AProjectile::SpawnTrailSystem()
{
	if(TrailSystem)
	{
		//UNiagaraFunctionLibrary：C++和Blueprint可访问的实用函数库，用于访问Niagara模拟
		//SpawnSystemAttached：孵化Niagara系统吸附在某个组件
		TrailSystemCommponent = UNiagaraFunctionLibrary::SpawnSystemAttached(TrailSystem, GetRootComponent(), FName(), GetActorLocation(), GetActorRotation(), EAttachLocation::KeepWorldPosition, false);
	}
}

void AProjectile::StartDestroyTimer()
{
	GetWorldTimerManager().SetTimer(DestroyTimer, this, &AProjectile::DestroyTimeFinished, DestroyTime);
}


void AProjectile::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AProjectile::Destroyed()
{
	Super::Destroyed();
	if(ImpactParticles)
	{
		UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactParticles, GetActorTransform());
	}
	if(ImpactSound)
	{
		//SpawnSoundAttached：播放音效吸附并跟随某具体组件
		//PlaySoundAtLocation：播放音效在指定位置
		//SpawnSoundAtLocation：在指定位置孵化音效
		UGameplayStatics::PlaySoundAtLocation(this, ImpactSound, GetActorLocation());
	}
}

